/*
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 *
 * Copyright @2008 the original author or authors.
 */
package com.bluestone.report;

import java.lang.reflect.Method;
import java.util.HashMap;

import com.bluestone.core.Command;
import com.bluestone.core.IAction;
import com.bluestone.core.Project;
import com.bluestone.core.TestCase;
import com.bluestone.core.TestSuite;
import com.bluestone.util.Util;

/**
 * @author <a href="mailto:ming7655@gmail.com">Aaron</a>
 * 
 * 
 */
public class ReportBeanFactory {
	private static HashMap reportBeans = new HashMap();
	

	public static ProjectReportBean createProjectReportBean(Project project) {
		ProjectReportBean projectReportBean = new ProjectReportBean();
		if (project == null) {
			project = Util.getCurrentProject();
		}
		if (project != null) {
			projectReportBean.setProjectId(project.getProjectId());
			projectReportBean.setProjectName(project.getName());
			projectReportBean.setProjectRetryCount(project.getRetrycount());
			projectReportBean.setProjectSpeedRate(project.getSpeedrate());
			projectReportBean.setProjectVersion(project.getVersion());
			projectReportBean.setBrowserType(project.getBrowser().getType());
		}
		projectReportBean.addExpAttributeHandler(createExpAttributeHandler(IExpAttributeHandler.TYPE_PROJECT));
		return projectReportBean;
	}

	private static TestSuiteReportBean createTestSuiteReportBean(TestSuite ts) {
		String key = String.valueOf(ts.hashCode());
		if (reportBeans.containsKey(key)) {
			return (TestSuiteReportBean) reportBeans.get(key);
		} else {
			TestSuiteReportBean tsrb = new TestSuiteReportBean();
			tsrb.setTestSuiteId(ts.getTestSuitId());
			tsrb.setTestSuiteName(ts.getName());
			tsrb.addExpAttributeHandler(createExpAttributeHandler(IExpAttributeHandler.TYPE_TESTSUITE));
			reportBeans.put(key, tsrb);
			return tsrb;
		}
	}
	
	private static TestCaseReportBean createTestCaseReportBean(TestCase tc) {
		String key = String.valueOf(tc.hashCode());
		if (reportBeans.containsKey(key)) {
			return (TestCaseReportBean) reportBeans.get(key);
		} else {
			TestCaseReportBean tcrb = new TestCaseReportBean();
			tcrb.setTestCaseId(tc.getTestCaseId());
			tcrb.setTestCaseAttributeId(tc.getId());
			tcrb.setTestCaseName(tc.getName());
			tcrb.addExpAttributeHandler(createExpAttributeHandler(IExpAttributeHandler.TYPE_TESTCASE));
			reportBeans.put(key, tcrb);
			return tcrb;
		}
	}
	
	private static CommandReportBean createCommandReportBean(Command command){
		String key = String.valueOf(command.hashCode());
		if(reportBeans.containsKey(key)){
			return (CommandReportBean)reportBeans.get(key);
		}else{
			CommandReportBean crb = new CommandReportBean();
			crb.setCommandId(command.getCommandId());
			crb.setCommandName(command.getName());
			crb.addExpAttributeHandler(createExpAttributeHandler(IExpAttributeHandler.TYPE_COMMAND));
			reportBeans.put(key, crb);
			return crb;
		}
	}
	
	private static ActionReportBean createActionReportBean(IAction action){
		String key = String.valueOf(action.hashCode());
		if(reportBeans.containsKey(key)){
			return (ActionReportBean)reportBeans.get(key);
		}else{
			ActionReportBean rb = new ActionReportBean();
//			 init action attributes
			rb.setActionId(getStringValue(Util.invokeClassOfMethod(action,
					"getId", null)));
			rb.setActionType(getStringValue(Util.invokeClassOfMethod(action,
					"getType", null)));
			rb.setActionValue(getStringValue(Util.invokeClassOfMethod(action,
					"getValue", null)));
			rb.setActionTarget(getStringValue(Util.invokeClassOfMethod(action,
					"getTarget", null)));
			rb.setActionDelay(getStringValue(Util.invokeClassOfMethod(action,
					"getDelay", null)));
			rb.setActionOffset(getStringValue(Util.invokeClassOfMethod(action,
					"getOffset", null)));
			rb.setActionOwner(getStringValue(Util.invokeClassOfMethod(action,
					"getOwner", null)));
			rb.setActionTimeOut(getStringValue(Util.invokeClassOfMethod(action,
					"getTimeOut", null)));
			// init action expand attribute
			initActionExpAttributes(rb, action);
			return rb;
		}
	}
	
	private static void initActionExpAttributes(ActionReportBean rb, IAction action) {
		String pre = "get" + IAction.ATTR_PREFIX;
		Class c = action.getClass();
		Method[] methods = c.getMethods();
		if (methods == null) {
			return;
		}
		for (int i = 0; i < methods.length; i++) {
			String methodName = methods[i].getName();
			if (methodName.startsWith(pre)) {
				try {
					rb.putExpAttribute(methodName.substring(3),
							getStringValue(methods[i].invoke(action, null)));
				} catch (Exception e) {
					Util.error(e);
				}
			}
		}
	}

	
	private static String getStringValue(Object obj) {
		return String.valueOf(obj);
	}
	
	public static AbstractReportBean createAbstractReportBean(Object obj){
		AbstractReportBean rb = null;
		if(TestSuite.class.isInstance(obj)){
			rb= createTestSuiteReportBean((TestSuite)obj);			
		}else if(TestCase.class.isInstance(obj)){
			rb= createTestCaseReportBean((TestCase)obj);			
		}else if(Command.class.isInstance(obj)){
			rb=createCommandReportBean((Command)obj);			
		}else if(IAction.class.isInstance(obj)){
			rb= createActionReportBean((IAction)obj);
		}
		return rb;
	}
	
	public static IExpAttributeHandler createExpAttributeHandler(String type){
		IExpAttributeHandler handler = null;
		if(IExpAttributeHandler.TYPE_COMMAND.equals(type)){
			handler= new CommandExpAttributeHandler();
		}else if(IExpAttributeHandler.TYPE_TESTSUITE.equals(type)){
			handler= new TestSuiteExpAttributeHandler();
		}else if(IExpAttributeHandler.TYPE_TESTCASE.equals(type)){
			handler=new TestCaseExpAttributeHandler();
		}else if(IExpAttributeHandler.TYPE_PROJECT.equals(type)){
			handler= new ProjectExpAttributeHandler();
		}
		return handler;
	}

}
